--[[
  author: blog.163.com/mr_zyf/
]]

require "tools/extern"
--子弹声效文件路径
local projectileEffectPath=CCFileUtils:sharedFileUtils():fullPathForFilename("effect1.wav")

--子弹声效播放ID
local projectileEffectId=nil

--gameLogicScheduleScriptFuncID
local gameLogicEntry=nil

--tolua.cast的函数引用
local clsCast=tolua.cast

--sharedDirector的引用
local sharedDirector=CCDirector:sharedDirector()

--sharedAudioEngine的引用
local sharedAudioEngine=SimpleAudioEngine:sharedEngine()

--构建继承CCLayerColor的GameLayer类表
local GameLayer=class("GameLayer",function() 
     return CCLayerColor:create(ccc4(255,0,255,125))
end)
--表的调用索引指向GameLayer 
GameLayer.__index=GameLayer

--GameLayer的初启化
function GameLayer:lInit()
   --self的引用
   local that=self
   --子弹击中目标的个数
   self._projectilesDestroyed=0
   --屏幕的可视Size
   local visibleSize = sharedDirector:getVisibleSize()

   --创建关闭游戏的菜单项
   local menuItem=CCMenuItemImage:create("CloseNormal.png", "CloseSelected.png")
   --设置关闭菜单项的位置坐标
   menuItem:setPosition(ccp(visibleSize.width-20,visibleSize.height-20))
   --设置关闭菜单项的回调函数
   local function menuItemCloseCallBack()
       that:menuCloseCallBack()  
   end
   menuItem:registerScriptTapHandler(menuItemCloseCallBack)
   local menu=CCMenu:createWithItem(menuItem)
   menu:setPosition(0,0)
   self:addChild(menu,1)
   
   --创建玩家精灵，并且设置位置
   local player = CCSprite:create("Player.png", CCRectMake(0, 0, 27, 40))
   player:setPosition( ccp(player:getContentSize().width/2, visibleSize.height/2))
   self:addChild(player,0)

   --创建目标精灵和子弹精灵的成员数组
   local targets = CCArray:create()
   targets:retain()
   local projectiles=CCArray:create()
   projectiles:retain()
   self._targets=targets
   self._projectiles=projectiles

   --设置GameLayer引发事件的回调函数
   local function onNodeEvent(event)
     cclog("gameLayer event:"..event)
     if event=="cleanup" then
        that:lCleanUp()
     elseif event == "exit" then
        that:lOnExit()
     elseif event=="enter" then
        that:lOnEnter()
     end
   end
   self:registerScriptHandler(onNodeEvent)
   
   --设置屏幕触摸事件的回调函数
   local function onTouch(event,x,y)

    if event == "ended" then
        return that:lccTouchEnded(x, y)
    end
    return true
   end
   self:setTouchEnabled(true)
   self:registerScriptTouchHandler(onTouch)
  
   --订制update的回调函数
   local function update(dt)
     that:lUpdate(dt)
   end
   self:scheduleUpdateWithPriorityLua(update,0)
   cclog("gameLayer lInit ok!")
  -- cclogSave()
end

--增加目标精灵的成员函数
function GameLayer:addTarget()
   local target = CCSprite:create("Target.png", CCRectMake(0, 0, 27, 40))
   local targetContentSize=target:getContentSize()	
    
    --在屏幕最右边，并且沿Y轴的随机位置，生成目标精灵
    local winSize = sharedDirector:getVisibleSize();
    local minY = targetContentSize.height/2;
    local maxY = winSize.height - targetContentSize.height/2;
    local actualY = math.random (minY,maxY)
    target:setPosition(winSize.width + targetContentSize.width/2, actualY)
    self:addChild(target)
    
    -- 目标精灵的移动间隔
    local minDuration = 2.0
    local maxDuration = 4.0
    local actualDuration = math.random(minDuration,maxDuration)
    -- 创建从屏幕右边移动到左边的action
    local actionMove = CCMoveTo:create(actualDuration, ccp(-targetContentSize.width/2, actualY))
    local that=self
    local function spriteMoveFinished(node)
        that:spriteMoveFinished(node)
    end
    --创建精灵移动结束的回调action
    local actionMoveDone = CCCallFuncN:create(spriteMoveFinished)
    --设置目标精灵的标签为1
    target:setTag(1)

    self._targets:addObject(target)

    target:runAction(CCSequence:createWithTwoActions(actionMove, actionMoveDone))
    cclog("gameLayer addTarget","Ok")
end

--关闭菜单项的回调函数
function GameLayer:menuCloseCallBack()
    sharedDirector:endToLua()
end

--exit事件的回调函数
function GameLayer:lOnExit()
    
    if projectileEffectId ~= nil then
       SimpleAudioEngine:sharedEngine():stopEffect(projectileEffectId)
    end	
    
    SimpleAudioEngine:sharedEngine():unloadEffect(projectileEffectPath)
    
    
    self:getScheduler():unscheduleScriptEntry(gameLogicEntry)
    
    cclog("gameLayer lOnExit")
    --cclogSave()
end

--cleanup事件的回调函数
function GameLayer:lCleanUp()
   self._targets:release()
   self._projectiles:release()
   cclog("gameLayer lcleanUp")
   cclogSave()
end

--enter事件回调函数
function GameLayer:lOnEnter()
   local that=self
      
    
   sharedAudioEngine:preloadEffect(projectileEffectPath)
   
   
   local function gameLogic(dt)
      that:gameLogic(dt)
   end
   
   gameLogicEntry=self:getScheduler():scheduleScriptFunc(gameLogic,1.0,false)
   cclog("gameLayer lOnEnter")
   --cclogSave()

end
--触摸事件ended回调，发射子弹
function GameLayer:lccTouchEnded(x,y)
	local winSize = sharedDirector:getVisibleSize()
	local projectile = CCSprite:create("Projectile.png", CCRectMake(0, 0, 20, 20))
        --设置子弹的发射位置
	projectile:setPosition(ccp(20, winSize.height/2))
        local projectilePosX,projectilePosY=projectile:getPosition()

	--local projectilePosX=projectile:getPosition().x--error
        --local projectilePosY=projectile:getPosition().y--error

	
	-- 计算子弹发射位置与点击位置的偏移量
	local offX = x - projectilePosX
	local offY = y - projectilePosY

	-- X偏移量小于等于零时，子弹精灵不会被增加到gameLayer中
	if offX <= 0 then return; end
	
	self:addChild(projectile)
	
	-- 计算子弹射出后，最终到达的位置
	local realX = winSize.width + (projectile:getContentSize().width/2)
	local ratio = offY/offX
	local realY = (realX * ratio) + projectilePosY
	local realDest = ccp(realX, realY)
	
	-- 计算子弹移动的间隔
	local offRealX = realX - projectilePosX
	local offRealY = realY - projectilePosY
	local length =math.sqrt((offRealX*offRealX)+(offRealY*offRealY))
	local velocity = 480/1 -- 480pixels/1sec
	local realMoveDuration = length/velocity
	
	projectile:setTag(2)--设置子弹的标签为2

	self._projectiles:addObject(projectile)
	
	-- 子弹移动到终点位置的action
	local actionRealMove=CCMoveTo:create(realMoveDuration,realDest)

        local that=self
        local function spriteMoveFinished(node)
              that:spriteMoveFinished(node)
        end
        --子弹移动结束后的回调
       local actionRealMoveDone=CCCallFuncN:create(spriteMoveFinished)

       projectile:runAction(CCSequence:createWithTwoActions(actionRealMove, actionRealMoveDone))
       cclog("gameLayer tag 2 projectile:runAction!")
       --播放子弹音效
       projectileEffectId=sharedAudioEngine:playEffect(projectileEffectPath)
       cclog("gameLayer lccTouchesEnded!") 
      return true
end
--订制gameLogic回调
function GameLayer:gameLogic(dt)
   self:addTarget()
   --cclog("gameLayer gameLogic")
end
--订制update回调,检测子弹是否命中目标精灵
function GameLayer:lUpdate(dt)
	local projectilesToDelete = CCArray:create()
	local projectiles=self._projectiles
        local targets=self._targets
        local projectilesDestroyed=self._projectilesDestroyed
        for i=0,projectiles:count()-1 do
          local projectile=clsCast(projectiles:objectAtIndex(i),"CCSprite")
          local projectilePosX,projectilePosY=projectile:getPosition()
          local projectileContentSize=projectile:getContentSize()
          local projectileRect=CCRectMake(
            projectilePosX - (projectileContentSize.width/2),
            projectilePosY - (projectileContentSize.height/2),
            projectileContentSize.width,
            projectileContentSize.height 
          )
          local targetsToDelete=CCArray:create()
          for j=0,targets:count()-1 do
             local target=clsCast(targets:objectAtIndex(j),"CCSprite")
             local targetPosX,targetPosY=target:getPosition()
             local targetContentSize=target:getContentSize()
             local targetRect=CCRectMake(
             targetPosX - (targetContentSize.width/2),
	     targetPosY - (targetContentSize.height/2), 
	     targetContentSize.width, 
	     targetContentSize.height
             )
            if projectileRect:intersectsRect(targetRect) then --检测子弹与目标精灵的碰撞
                targetsToDelete:addObject(target)
	    end

          end
          for k=0,targetsToDelete:count()-1 do
              local o=targetsToDelete:objectAtIndex(k)
              targets:removeObject(o)
              --local jt=clsCast(o,"CCSprite")
	      --self:removeChild(jt, true)
	      self:removeChild(o,true)

              projectilesDestroyed=projectilesDestroyed+1
              if projectilesDestroyed>30 then--命中目标精灵个数大于30时，玩家获胜进入GameOverScene
                 projectilesDestroyed=0
                 self._projectilesDestroyed=0
                 --GameOverScene
                 self:replaceGameOverScene("You Win!")
                 cclog("gamelayer replaced Win!")
              end
               
          end
          if targetsToDelete:count()>0 then
             projectilesToDelete:addObject(projectiles:objectAtIndex(i))
          end
        end
        self._projectilesDestroyed=projectilesDestroyed

        for i=0,projectilesToDelete:count()-1 do
            local o=projectilesToDelete:objectAtIndex(i)
            projectiles:removeObject(o)
            --local p=clsCast(o,"CCSprite")
            --self:removeChild(p,true)
            self:removeChild(o,true)
        end
	cclog("lUpdate","Ok")
end
--置换GameOver场景
function GameLayer:replaceGameOverScene(str)
   local scene=CCScene:create()
   local GameOverLayer=require("gameOverLayer")
   local layer=GameOverLayer:lCreate()
   scene:addChild(layer)
   layer:setString(str)
   sharedDirector:replaceScene(scene) 
end
--精灵移动结束后的回调函数
function GameLayer:spriteMoveFinished(node)
        self:removeChild(node, true)--从GameLayer中,删除精灵 
        cclog("gameLayer spriteMoveFinished removeChild:"..tostring(node)) 
	if node:getTag() == 1 then --node的标签为1时，node为目标精灵 
	 
	 self._targets:removeObject(node)-- 从目标精灵数组中，删除目标精灵
         
         cclog("gameLayer spriteMoveFinished tag:1")

	 self:replaceGameOverScene("You Lose! :[")--进入GameOver场景
	
	elseif node:getTag() == 2 then --node的标签为2时，node为子弹精灵
	
         self._projectiles:removeObject(node)-- 从子弹精灵数组中，删除子弹精灵
	cclog("gameLayer spriteMoveFinished tag:2")
        end
end
--生成GameLayer对象实例
function GameLayer:lCreate()
   local o=GameLayer.new()
   o:lInit()
   return o
end
return GameLayer
